﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using GRV11;

namespace gpuimp.core
{
    [Serializable]
    public class LayerManager
    {
        private int activeLayer;
        private List<Layer> layers;
        private Canvas canvas;

#region Properties
        public int ActiveLayer
        {
            get { return activeLayer; }
            set { activeLayer = value; }
        }

        public List<Layer> Layers
        {
            get { return layers; }
        }
#endregion

#region Constructors/Destructors
        /// <summary>
        /// Create a new layer manager instance.  Creates and adds one layer.
        /// </summary>
        public LayerManager(Canvas canvas)
        {
            this.canvas = canvas;
            //Layer layer = new Layer(canvas.ImageSize);
            layers = new List<Layer>();
            //addLayer(layer);
            activeLayer = 0;
        }

        ~LayerManager()
        {
        }
#endregion

#region Methods
        /// <summary>
        /// Adds a layer
        /// </summary>
        /// <param name="layer">layer to be added</param>
        /// <returns>True if layer successfully added. False otherwise</returns>
        public bool addLayer(Layer layer)
        {
            if (layer == null)
                return false;

            layers.Add(layer);

            if (layers.Count == 1)
            {
                CanvasManager.getCanvas(canvas.ID).StateManager.addState(layers[0], "Base");
            }

            activeLayer = layers.Count - 1;

            return true;
        }

        /// <summary>
        /// Adds a transparent layer
        /// </summary>
        /// <param name="x">Width of the Layer</param>
        /// <param name="y">Height of the Layer</param>
        /// <returns>True if layer successfully added.  False otherwise</returns>
        public bool addTransparentLayer(int x, int y)
        {
            System.Drawing.Bitmap transparentLayer = new System.Drawing.Bitmap(x, y);

            for(int i = 0; i < x; i++)
            {
                for(int j = 0; j < y; j++)
                {
                    transparentLayer.SetPixel(i, j, System.Drawing.Color.Transparent);
                }
            }

            layers.Add(new Layer(transparentLayer));

            activeLayer = layers.Count - 1;

            return true;
        }

        /// <summary>
        /// Moves the specified layer to a new position
        /// </summary>
        /// <param name="id">Layer to be moved</param>
        /// <param name="position">Position to move the layer to</param>
        /// <returns>True if layer successfully moved. False otherwise</returns>
        public bool changeLayerOrder(int id, int position)
        {
            Layer layerToMove = null;
            int oldPos = -1;

            for (int i = 0; i < layers.Count; i++)
            {
                if (layers[i].ID == id)
                {
                    oldPos = i;
                    layerToMove = layers[i];
                    break;
                }
            }

            if (oldPos == -1)
                return false; //no matching layer

            layers.RemoveAt(oldPos);
            layers.Insert(position, layerToMove);

            return true;
        }

        /// <summary>
        /// Remove a layer from the list.
        /// </summary>
        /// <param name="id">ID of the layer to be removed</param>
        /// <returns>True if layer succesfully removed. False otherwise</returns>
        public bool deleteLayer(int id)
        {
            int pos = -1;
            for (int i = 0; i < layers.Count; i++)
            {
                if (layers[i].ID == id)
                {
                    pos = i;
                    break;
                }
            }

            if (pos == -1)
                return false;

            layers.RemoveAt(pos);

            activeLayer--;
            
            return true;
        }

        public void DrawModifiers(GR gr)
        {
            foreach (Layer l in layers)
            {
                if (l.IsVisible)
                {
                    l.DrawModifiers(gr);
                }
            }
        }

        /// <summary>
        /// Loop through, and draw all visible layers.
        /// </summary>
        public void Draw(GR gr, float layerSpacing)
        {
            int count = 0;

            for (int i = 0; i < layers.Count; i++)
            {
                if (layers[i].IsVisible)
                {
                    gr.glPushMatrix();
                    gr.glTranslatef(0, 0, -layerSpacing * i);
                    layers[i].Draw(gr, true, true);
                    gr.glPopMatrix();
                }
            }
        }

        /// <summary>
        /// Find and return the ID for a layer with the matching name.
        /// </summary>
        /// <param name="name">Name of a layer to look for</param>
        /// <returns>ID of the layer if found. -1 if no layer found.</returns>
        public int getLayerID(string name)
        {
            foreach (Layer l in layers)
            {
                if (l.Name == name)
                    return l.ID;
            }

            return -1;
        }

        /// <summary>
        /// Returns a layer by its id number
        /// </summary>
        /// <param name="id">ID of the layer to get</param>
        /// <returns>Layer if found. Null if none match id.</returns>
        public Layer getLayerByID(int id)
        {
            foreach (Layer l in layers)
            {
                if (l.ID == id)
                    return l;
            }
            return null;
        }
#endregion
    }
}
